package com.liu.www;

/**
 * 类的说明:大数据阶乘的实现.
 * @author liuzd
 */
public class Test_004 {
	public static void main(String[] args) {
		String[] str = getFactorialBigValue(20000);
		print(str);

	}

	private static final int STACK_FLOW = 5000;
	
	/**
	 * 操作：打印数组
	 * 刘柱栋    2013-4-10
	 * @param n
	 */
	private static void print(Object[] n) {
		int times = 0;
		for (Object s : n) {
			times++;
			if (times % 10 == 0) {
				System.out.println();
			}
			System.out.print(s);
		}
		System.out.println();
	}

	/**
	 * 操作：阶乘的计算.<br>
	 * 备注：value值不能太大，这里设为5000最大.
	 * 刘柱栋    2013-4-10
	 * @param value
	 * @return
	 */
	private static String[] getFactorialBigData(int value) {
		if(value > STACK_FLOW){
			return null;
		}
		String[] strs = new String[] { "0001" };
		if (value > 1) {
			strs = countMul(value, getFactorialBigData(value - 1));
		}
		return strs;
	}

	/**
	 * 操作：计算超过5000的阶乘.<br>
	 * 刘柱栋    2013-4-10
	 * @param value
	 * @return
	 */
	private static String[] getFactorialBigValue(int value) {
		if (value <= STACK_FLOW) {
			return getFactorialBigData(value);
		} else {
			int counts = STACK_FLOW + 1;
			System.out.println("==============" + System.currentTimeMillis() / 1000);
			String[] str = getFactorialBigData(STACK_FLOW);
			System.out.println("==============" + System.currentTimeMillis() / 1000);
			while (counts <= value) {
				str = countMul(counts, str);
				counts++;
			}
			System.out.println("==============" + System.currentTimeMillis() / 1000);
			return str;
		}
	}

	private static int[] splitLongStr(long value, int step) {
		int[] result = new int[2];
		String str = value + "";
		int size = str.length();
		if (size <= step) {
			result[0] = (int) value;
		} else {
			String s0 = new String(str.substring(size - step));
			String s1 = new String(str.substring(0, size - step));
			result[0] = Integer.parseInt(s0);
			result[1] = Integer.parseInt(s1);
		}
		return result;
	}

	private static int[] splitLongStr(int value, int count, int bit) {
		int step = (count + "").length();
		long temp = value * count + bit;
		return splitLongStr(temp, step);
	}

	private static int[] splitLongStr(int value, String count, int bit, int size) {
		int temp = Integer.parseInt(count);
		long sum = value * temp + bit;
		return splitLongStr(sum, size);
	}

	private static int[] countMul(int value, int[] counts) {
		int size = counts.length;
		int[] result = new int[size + 1];
		int temp = 0;
		int j = size;
		for (int i = size - 1; i >= 0; i--) {
			int sums[] = splitLongStr(value, counts[i], temp);
			result[j--] = sums[0];
			temp = sums[1];
		}
		result[0] = temp;
		return result;
	}

	/**
	 * 操作：格式化字符串.<br>
	 * 刘柱栋    2013-4-10
	 * @param a
	 * @param size
	 * @return
	 */
	private static String formatStrFromInt(int a, int size) {
		String str = a + "";
		if (str.length() < size) {
			int j = size - str.length();
			for (int i = 0; i < j; i++) {
				str = "0" + str;
			}
		}
		return str;
	}

	/**
	 * 操作：大数据的乘法运算.<br>
	 * 刘柱栋    2013-4-10
	 * @param value
	 * @param strs
	 * @return
	 */
	private static String[] countMul(int value, String[] strs) {
		if (strs == null) {
			return null;
		}
		int temp = 0;
		for (int i = strs.length - 1; i >= 0; i--) {
			int sums[] = splitLongStr(value, strs[i], temp, 4);
			if (i != 0) {
				strs[i] = formatStrFromInt(sums[0], 4);
			} else {
				strs[i] = sums[0] + "";
			}
			temp = sums[1];
		}
		if (temp > 0) {
			strs[0] = formatStrFromInt(Integer.parseInt(strs[0]), 4);
			String[] s = new String[strs.length + 1];
			s[0] = temp + "";
			int i = 1;
			for (String sss : strs) {
				s[i++] = sss;
			}
			return s;
		}
		return strs;
	}

}
